<script setup lang="ts">
  import { computed, PropType, ref, watch } from 'vue'
  import { ComponentTypeRow, ComponentListItem } from '../../hooks/types'
  import CustomInput from '../component-list/CustomInput.vue'
  import CustomTextarea from '../component-list/CustomTextarea.vue'
  import CustomRadio from '../component-list/CustomRadio.vue'
  import CustomCheckbox from '../component-list/CustomCheckbox.vue'
  import CustomSingleSelect from '../component-list/CustomSingleSelect.vue'
  import CustomMultipleSelect from '../component-list/CustomMultipleSelect.vue'
  import CustomDivider from '../component-list/CustomDivider.vue'
  import CustomDateTime from '../component-list/CustomDateTime.vue'
  import CustomFileUpload from '../component-list/CustomFileUpload.vue'
  import CustomAddress from '../component-list/CustomAddress.vue'
  import CustomDataConnect from '../component-list/custom-data-connect/Index.vue'
  import CustomChildForm from '../component-list/CustomChildForm.vue'
  import { useTemplateForm } from '../../hooks/useTemplate'
  import _ from 'lodash'

  const {
    componentList,
    addComponent,
    swapComponentOrder,
    delComponentByIndex,
    updateComponentListByComponent,
  } = useTemplateForm()

  defineOptions({
    name: 'OrderCustomFormScreen',
  })

  const props = defineProps({
    componentType: {
      type: Object as PropType<ComponentTypeRow>,
      default: () => {
        return {
          type: '',
          text: '',
        }
      },
    },
    needUpdateComponent: {
      type: Object as PropType<ComponentListItem>,
      default: () => {
        return {
          type: 'input',
          placeholder: '',
          label: '',
          no: -1,
        }
      },
    },
  })

  const emits = defineEmits<{
    (e: 'component-click', value: ComponentListItem): void
  }>()

  const componentTypeIsDragEnter = ref(false)
  const isAddComponent = ref(true)
  const currentSelectComponent = ref<ComponentListItem | null>(null)
  const currentSelectComponentIndex = ref(-1)
  const componentDivList = ref<Array<HTMLDivElement>>([])
  const dragingComponent = ref<ComponentListItem | null>(null)
  const dragingComponentIndex = ref(-1)
  const componentWidthList = computed(() => {
    return componentList.value.map((item) => {
      if (item.width === '1/4') {
        return '25%'
      }

      if (item.width === '1/3') {
        return '33.33%'
      }

      if (item.width === '1/2') {
        return '50%'
      }

      if (item.width === '1') {
        return '100%'
      }
    })
  })

  const updateComponentDivSytle = () => {
    if (componentDivList.value) {
      componentDivList.value.forEach((component) => {
        component.style.backgroundColor = '#fff'
      })

      if (
        dragingComponentIndex.value >= 0 &&
        dragingComponentIndex.value <= componentDivList.value.length
      ) {
        componentDivList.value[dragingComponentIndex.value].style.backgroundColor = '#f2f8ff'
      }
    }
  }

  const clearComponentDivStyle = () => {
    if (componentDivList.value) {
      componentDivList.value.forEach((component) => {
        component.style.backgroundColor = ''
      })
    }
  }

  const handleComponentTypeDragOver = (e: Event) => {
    e.preventDefault()
  }

  const handleComponentTypeDragEnter = () => {
    componentTypeIsDragEnter.value = true
  }

  const handleComponentTypeDragLeave = () => {
    componentTypeIsDragEnter.value = false
  }

  const handleComponentTypeDrop = (e: Event) => {
    e.preventDefault()
    componentTypeIsDragEnter.value = false
    if (isAddComponent.value) {
      addComponent(props.componentType.type)
    }
  }

  const handleComponentDragStart = (e: Event, index: number) => {
    isAddComponent.value = false
    currentSelectComponentIndex.value = -1
    const component = componentList.value[index]
    dragingComponentIndex.value = index
    currentSelectComponent.value = null
    emits('component-click', currentSelectComponent.value)
    if (component) {
      dragingComponent.value = component
    }
    updateComponentDivSytle()
  }

  const handleComponentDragEnd = () => {
    isAddComponent.value = true
    dragingComponent.value = null
    dragingComponentIndex.value = -1
    updateComponentDivSytle()
    clearComponentDivStyle()
  }

  const handleComponentClick = (index: number) => {
    const component = componentList.value[index]
    currentSelectComponentIndex.value = index
    if (component) {
      currentSelectComponent.value = component
      emits('component-click', _.cloneDeep(component))
      if (componentDivList.value) {
        componentDivList.value.forEach((component) => {
          component.style.backgroundColor = '#fff'
        })

        if (componentDivList.value[index]) {
          componentDivList.value[index].style.backgroundColor = 'rgba(0, 124, 255, 0.05)'
        }
      }
    }
  }

  const handleComponentDragEnter = (e: Event, index: number) => {
    swapComponentOrder(dragingComponentIndex.value, index)
    dragingComponentIndex.value = index
    updateComponentDivSytle()
  }

  const handleComponentDragOver = (e: Event) => {
    e.preventDefault()
  }

  const handleComponentDelClick = (componentIndex: number) => {
    const component = _.cloneDeep(componentList.value[componentIndex])
    delComponentByIndex(componentIndex)
    component.dataConnectConfig.fillRules.forEach((fillRule) => {
      const componentIndex = componentList.value.findIndex((item) => item.id === fillRule.toFieldId)
      if (componentIndex !== -1) {
        delComponentByIndex(componentIndex)
      }
    })
    emits('component-click', null)
  }

  const handleComponentDelCancelClick = (componentIndex: number) => {
    const component = _.cloneDeep(componentList.value[componentIndex])
    if (component) {
      component.delPopoverVisible = false
      updateComponentListByComponent(component)
    }
  }

  watch(
    () => props.needUpdateComponent,
    (value) => {
      updateComponentListByComponent(value)
    },
    { deep: true },
  )
</script>

<template>
  <div
    :class="{
      'order-custom-form-screen': true,
      'is-component-type-enter': componentTypeIsDragEnter,
    }"
    @dragover="handleComponentTypeDragOver"
    @dragenter="handleComponentTypeDragEnter"
    @drop="handleComponentTypeDrop"
    @dragleave="handleComponentTypeDragLeave"
  >
    <transition-group name="fade" tag="div" class="component-list">
      <div
        v-for="(component, componentIndex) in componentList"
        :key="componentIndex"
        ref="componentDivList"
        class="component-item"
        :style="{
          width: component.type === 'divider' ? '100%' : componentWidthList[componentIndex],
        }"
        draggable="true"
        @dragstart="(e: Event) => handleComponentDragStart(e, componentIndex)"
        @dragend="handleComponentDragEnd"
        @click="handleComponentClick(componentIndex)"
        @dragenter="(e: Event) => handleComponentDragEnter(e, componentIndex)"
        @dragover="handleComponentDragOver"
      >
        <div class="header">
          <div class="label">
            <i v-if="component.beAssociated" class="iconfont icon-lianjie"></i>
            <div v-if="component.required" class="required-symbol">*</div>
            <div class="text">{{ component.label }}</div>
          </div>
          <div class="btn-group">
            <el-popover :visible="component.delPopoverVisible" :width="200" placement="bottom-end">
              <template #reference>
                <div class="del-btn" @click="component.delPopoverVisible = true">
                  <i class="iconfont icon-shanchu1"></i>
                </div>
              </template>

              <div class="field-del-panel">
                <div class="title">提示</div>
                <div class="content">确定要删除该组件吗？</div>
                <div class="footer">
                  <h-plain-button
                    type="error"
                    :height="18"
                    :width="36"
                    @click="handleComponentDelClick(componentIndex)"
                  >
                    确定
                  </h-plain-button>
                  <h-button
                    :height="18"
                    :width="36"
                    @click="handleComponentDelCancelClick(componentIndex)"
                  >
                    取消
                  </h-button>
                </div>
              </div>
            </el-popover>
          </div>
        </div>
        <template v-if="component.type === 'divider'">
          <custom-divider
            :title="component.dividerConfig.title"
            :title-color="component.dividerConfig.titleColor"
            :divider-color="component.dividerConfig.dividerColor"
            :desc="component.dividerConfig.desc"
            :style="component.dividerConfig.style"
          />
        </template>
        <template v-else>
          <!-- 单行输入 -->
          <custom-input
            v-if="component.type === 'input'"
            :placeholder="component.inputConfig.placeholder"
            :amount-max="component.inputConfig.amountMax"
            :number-max="component.inputConfig.numberMax"
            :mode="component.inputConfig.mode"
            disabled
          />

          <!-- 多行输入 -->
          <custom-textarea
            v-if="component.type === 'textarea'"
            :placeholder="component.textareaConfig.placeholder"
            :maxlength="component.textareaConfig.maxLength"
            disabled
          />

          <!-- 单选 -->
          <custom-radio
            v-if="component.type === 'radio'"
            :options="component.radioConfig.options"
            disabled
          />

          <!-- 多选 -->
          <custom-checkbox
            v-if="component.type === 'checkbox'"
            :options="component.checkboxConfig.options"
            disabled
          />

          <!-- 下拉单选 -->
          <custom-single-select
            v-if="component.type === 'single-select'"
            :options="component.singleSelectConfig.options"
            :placeholder="component.singleSelectConfig.placeholder"
            disabled
          />

          <!-- 下拉多选 -->
          <custom-multiple-select
            v-if="component.type === 'multiple-select'"
            :options="component.multipleSelectConfig.options"
            :placeholder="component.multipleSelectConfig.placeholder"
            disabled
          />

          <!-- 日期时间 -->
          <custom-date-time
            v-if="component.type === 'date-time'"
            :datetime-type="component.dateTimeConfig.dateTimeType"
            :placeholder="component.dateTimeConfig.placeholder"
            disabled
          />

          <!-- 文件上传 -->
          <custom-file-upload
            v-if="component.type === 'file-upload'"
            :size="component.fileUploadConfig.size"
            :num="component.fileUploadConfig.num"
            :upload-type="component.fileUploadConfig.type"
            disabled
          />

          <!-- 地址选择 -->
          <custom-address v-if="component.type === 'address'" disabled />

          <!-- 关联数据 -->
          <custom-data-connect
            v-if="component.type === 'data-connect'"
            :data-type="component.dataConnectConfig.type"
            :select-mode="2"
            disabled
            :field-list="component.dataConnectConfig.fieldList"
            :field-show-list-after-select="component.dataConnectConfig.showFormFieldList"
          />

          <!-- 子表单 -->
          <custom-child-form
            v-if="component.type === 'child-form'"
            :field-list="component.childFormConfig"
            disabled
          />
        </template>
      </div>
    </transition-group>
  </div>
</template>

<style scoped lang="scss">
  .field-del-panel {
    display: flex;
    flex-direction: column;

    .title {
      font-weight: bold;
      color: #000;
    }

    .content {
      white-space: nowrap;
    }

    .footer {
      display: flex;
      justify-content: flex-end;
      margin-top: 8px;
      column-gap: 4px;
    }
  }

  .is-component-type-enter {
    background-color: #f2f8ff;
  }

  .order-custom-form-screen {
    width: 100%;
    height: 100%;
    padding: 12px;
    box-sizing: border-box;
    overflow-y: auto;

    .component-list {
      display: flex;
      flex-wrap: wrap;
      max-height: 100%;
      overflow-y: auto;

      .component-item {
        width: 100%;
        box-sizing: border-box;
        padding: 12px;
        cursor: pointer;
        height: fit-content;
        display: flex;
        flex-direction: column;
        row-gap: 4px;
        transition: all ease-in-out 0.2s;
        position: relative;

        &:hover {
          background-color: #f2f8ff;
        }

        .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          height: 24px;

          .label {
            color: #000;
            font-weight: bold;
            display: flex;

            .iconfont {
              color: gray;
              margin-right: 4px;
            }

            .required-symbol {
              color: #f56c6c;
            }
          }

          .btn-group {
            .del-btn {
              width: 36px;
              height: 24px;
              border-radius: 4px;
              background-color: #fff;
              display: flex;
              justify-content: center;
              align-items: center;
              font-size: 10px;
              box-shadow: 0 0 5px rgba($color: #000000, $alpha: 0.1);
              transform: scale(0.8);

              &:hover {
                background-color: #feebe2;
                color: #f56c6c;
              }
            }
          }
        }
      }
    }
  }

  .fade-move {
    transition: all 0.5s ease-in-out;
  }
</style>
